package com.lincoln.framework.common;

import com.lincoln.framework.common.Constant;
import com.lincoln.framework.bean.LoginMember;
import com.lincoln.framework.bean.SysLoginAdmin;
import com.lincoln.framework.utils.ImageUtils;
import com.lincoln.framework.utils.FileUtilsEx;
import com.lincoln.framework.utils.FrameworkLogger;
import com.lincoln.framework.utils.StringUtilsEx;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.support.RequestContext;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * web助手类
 */
public final class WebUtils {

	private static FrameworkLogger logger = FrameworkLogger.initFrameworkLogger(WebUtils.class);

	/**
	 * 当前登录会话对象
	 */
	public static SysLoginAdmin getSysLoginAdmin() {
		return (SysLoginAdmin) getRequest().getSession().getAttribute(Constant.SESSION_SYS_ADMIN_LOGIN);
	}

	/**
	 * 保存系统管理员登录信息
	 * 
	 * @param admin
	 *            void
	 */
	public static void saveSysLoginAdmin(SysLoginAdmin admin) {
		getRequest().getSession().setAttribute(Constant.SESSION_SYS_ADMIN_LOGIN, admin);
	}

	/**
	 * 当前登录会话会员对象
	 */
	public static LoginMember getLoginMember() {
		return (LoginMember) getRequest().getSession().getAttribute(Constant.SESSION_MEMBER_LOGIN);
	}

	/**
	 * 保存系统会员登录信息
	 * 
	 * @param loginMember
	 *            void
	 */
	public static void saveLoginMember(LoginMember loginMember) {
		getRequest().getSession().setAttribute(Constant.SESSION_MEMBER_LOGIN, loginMember);
	}

	/**
	 * 获取客户来源ip地址
	 * 
	 * @return
	 */
	public static String getClientIp() {
		HttpServletRequest request = getRequest();
		// 负载均衡环境下获取原始请求ip地址
		if (!StringUtilsEx.isNullOrEmpty(request.getHeader("x-forwarded-for"))) {
			String xff = request.getHeader("x-forwarded-for");
			if (xff.indexOf(",") > 0) { // 做了多次重定向，取第一个ip地址
				return xff.substring(0, xff.indexOf(","));
			} else {
				return xff;
			}
		}
		return request.getRemoteAddr();
	}

	/**
	 * 获取客户来源地址
	 * 
	 * @return
	 */
	public static String getRefferUrl() {
		return getRequest().getHeader("referer");
	}

	/**
	 * 获取当前服务器根目录
	 * 
	 * @return
	 */
	public static String getContextPath() {
		return StringUtilsEx.getContextPath();
	}

	/**
	 * 获取上传图片文件临时目录
	 */
	public static String getTempUploadImgPath() {
		return getTempFilePath() + Constant.UPLOAD_DIR;
	}

	/**
	 * 临时目录
	 * 
	 * @return String
	 */
	public static String getTempFilePath() {
		return StringUtilsEx.getContextPath() + Constant.TEMP_DIR;
	}

	/**
	 * 获取上传图片文件临时目录uri
	 */
	public static String getTempUploadImgUri() {
		return Constant.TEMP_DIR + "/";
	}

	/**
	 * 系统端临时图片上传目录
	 */
	public static String getTempSysUploadImgUri() {
		return Constant.TEMP_DIR + "/sys" + "/";
	}

	/**
	 * 系统端图片上传目录
	 */
	public static String getSysUploadImgUri() {
		return Constant.UPLOAD_DIR + "/sys" + "/";
	}
	
	/**
	 * 前台图片上传目录
	 */
	public static String getSiteUploadImgUri() {
		return Constant.UPLOAD_DIR + "/site" + "/";
	}

	/**
	 * 获取绝对路径
	 * 
	 * @param uri
	 */
	public static String getAbsolutePath(String uri) {
		return getContextPath() + uri;
	}

	/**
	 * 判断如果是上传图片的临时目录 转成正式目录
	 * 
	 * @param tempImgPath
	 * @return
	 * @throws Exception
	 */
	public static String getRealImgPath(String tempImgPath) throws Exception {
		if (tempImgPath != null && (tempImgPath.startsWith(Constant.TEMP_DIR) || tempImgPath.startsWith(Constant.UEDITOR_TEMP_DIR))) {
			String imgName = tempImgPath.startsWith(Constant.TEMP_DIR) ? tempImgPath.substring(Constant.TEMP_DIR.length()) : tempImgPath.substring(Constant.UEDITOR_TEMP_DIR.length());
			String ext = FilenameUtils.getExtension(imgName);
			if (StringUtilsEx.isNullOrEmpty(ext)) {
				File tempFile = new File(getContextPath() + tempImgPath);
				if (tempFile.exists() && tempFile.isFile()) {
					return Constant.UPLOAD_DIR + imgName + "." + ImageUtils.getType(tempFile);
				}
			}
			return Constant.UPLOAD_DIR + imgName;
		}
		return tempImgPath;
	}

	/**
	 * 返回文件的正式上传目录
	 * 
	 * @param tempFilePath
	 * @return
	 * @throws Exception
	 */
	public static String getRealFilePath(String tempFilePath) throws Exception {
		String filePath = tempFilePath;
		if (filePath != null && filePath.startsWith(Constant.TEMP_DIR)) {
			String fileName = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length());
			filePath = Constant.UPLOAD_DOWNLOAD_DIR  + "/" + fileName;
		}
		return filePath;
	}

	/**
	 * 更新图片处理
	 * 
	 * @param newImgUrl
	 * @param oldImgUrl
	 * @return
	 * @throws IOException
	 */
	public static String updateImage(String newImgUrl, String oldImgUrl) throws Exception {
		String realUrl = getRealImgPath(newImgUrl);
		if (realUrl != null && realUrl.equals(newImgUrl) && realUrl.equals(oldImgUrl)) {
			return realUrl;
		}
		if (realUrl != null && !realUrl.equals(oldImgUrl)) {
			if (oldImgUrl != null && !oldImgUrl.trim().equals("")) {
				removeFile(oldImgUrl);
			}
			if (realUrl != null && !realUrl.trim().equals("")) {
				File tempFile = new File(getContextPath() + newImgUrl);
				if (tempFile.exists()) {
					File file = new File(getContextPath() + realUrl);
					FileUtils.copyFile(tempFile, file);
				}
			}
		}
		return realUrl;
	}
	
	/**
	 * 更新文件所在路径
	 * 
	 * @param fileUrl
	 * @return
	 * @throws Exception
	 */
	public static String updateFilePath(String fileUrl) throws Exception {
		String realUrl = getRealFilePath(fileUrl);
		if (realUrl != null && !realUrl.equals(fileUrl)) {
			File tempFile = new File(getContextPath() + fileUrl);
			File file = new File(getContextPath() + realUrl);
			FileUtils.copyFile(tempFile, file);
		}
		return realUrl;
	}

	/**
	 * html文本内容中的图片修改
	 * 
	 * @param oldContent
	 * @param newContent
	 * @return
	 * @throws IOException
	 */
	public static String updateContentImg(String oldContent, String newContent) throws IOException {
		return updateContentImg(oldContent, newContent, null);
	}

	/**
	 * 删除编辑框中的图片
	 * 
	 * @param content
	 */
	public static void deleteContentImg(String content) {
		Pattern pattern = Pattern.compile("<(?i)(img\\s+(?:[^>]*)\\s+src|img\\s+src)\\s*=\\s*\"([^>\\s*\"]+)",
				Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
		HttpServletRequest request = getRequest();
		String url = " src=\"" + request.getScheme() + "://" + request.getServerName();
		content = content.replaceAll(url, " src=\"");
		List<String> oldImgs = new ArrayList<String>();
		Matcher sourceMatcher = pattern.matcher(content);
		while (sourceMatcher.find()) {
			oldImgs.add(sourceMatcher.group(2));
		}
		for (String oldImg : oldImgs) {
			if (oldImg.startsWith(Constant.UPLOAD_DIR)) {
				removeFile(oldImg);
			}
		}
	}

	/**
	 * html文本内容中的图片修改
	 * 
	 * @param oldContent
	 * @param newContent
	 * @param path
	 * @return
	 * @throws IOException
	 */
	public static String updateContentImg(String oldContent, String newContent, String path) throws IOException {
		if (oldContent == null) {
			oldContent = "";
		}
		Pattern pattern = Pattern.compile("<(?i)(img\\s+(?:[^>]*)\\s+src|img\\s+src)\\s*=\\s*\"([^>\\s*\"]+)",
				Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

		HttpServletRequest request = getRequest();
		String url = " src=\"" + request.getScheme() + "://" + request.getServerName();
		newContent = newContent.replaceAll(url, " src=\"");

		List<String> oldImgs = new ArrayList<String>();
		Matcher sourceMatcher = pattern.matcher(oldContent);
		while (sourceMatcher.find()) {
			oldImgs.add(sourceMatcher.group(2));
		}

		List<String> newImgs = new ArrayList<String>();
		Matcher targetMatcher = pattern.matcher(newContent);
		while (targetMatcher.find()) {
			newImgs.add(targetMatcher.group(2));
		}

		for (String oldImg : oldImgs) {
			if (oldImg.startsWith(Constant.UPLOAD_DIR) && !newImgs.contains(oldImg)) {
				removeFile(oldImg);
			}
		}
		
		for (String newImg : newImgs) {
			if ((newImg.startsWith(Constant.TEMP_DIR) ||newImg.startsWith(Constant.UEDITOR_TEMP_DIR)) && !oldImgs.contains(newImg)) {
				try {
					String realUrl = "";
					if (path != null) {
						realUrl = FileUtilsEx.saveFile(newImg, path, true);
					} else {
						realUrl = updateImage(newImg, "");
					}
					newContent = newContent.replace(newImg, realUrl);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
			}
		}
		return newContent;
	}

	/**
	 * 删除文件/目录
	 * 
	 * @throws Exception
	 */
	public static void removeFile(String filePathName) {
		if (StringUtilsEx.isNullOrEmpty(filePathName)) {
			return;
		}
		// 只允许删除以下三个目录的文件内容
		String contextPath = getContextPath();
		File oldFile = new File(contextPath + filePathName);
		if (oldFile.exists()) {
			try {
				String fileCanonicalPath = oldFile.getCanonicalPath();
				String uploadCanonicalPath = new File(contextPath + Constant.UPLOAD_DIR).getCanonicalPath();
				String tempUploadCanonicalPath = new File(contextPath + Constant.TEMP_DIR).getCanonicalPath();

				if (fileCanonicalPath.startsWith(uploadCanonicalPath)
						|| filePathName.startsWith(tempUploadCanonicalPath)) {

					logger.log("删除文件：" + filePathName);
					FileUtils.deleteQuietly(oldFile);
				} else {
					throw new RuntimeException("删除文件路径【" + filePathName + "】非法");
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	/**
	 * 获取文件基本名称不含后缀
	 */
	public static String getBaseName(File file) {
		return file.getName().substring(0, file.getName().lastIndexOf('.'));
	}

	/**
	 * 获取文件基本名称
	 */
	public static String getBaseName(String fileName) {
		if (fileName.lastIndexOf("/") > -1) {
			fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
		}
		if (fileName.lastIndexOf('.') > 0) {
			fileName = fileName.substring(0, fileName.lastIndexOf('.'));
		}
		return fileName;

	}

	/**
	 * 保存到目标目录
	 * 
	 * @throws IOException
	 */
	public static String copyFile(String srcfilePath, String destDir) throws IOException {
		File srcFile = new File(getContextPath() + srcfilePath);
		File destFile = new File(getContextPath() + destDir + srcFile.getName());
		if (srcFile.isFile()) {
			FileUtils.copyFile(srcFile, destFile);
		}
		return destDir + srcFile.getName();
	}

	/**
	 * 检测目录是否存在并创建
	 */
	public static void initDir(String dir) {
		File directory = new File(dir);
		if (!directory.exists() || !directory.isDirectory()) {
			directory.mkdirs();
		}
	}

	/**
	 * 获取文件后缀
	 */
	public static String getFileExtention(String fileName) {
		int pos = fileName.lastIndexOf(".");
		if (pos > -1 && pos < fileName.length()) {
			return fileName.substring(pos + 1);
		}
		return "";
	}

	/**
	 * 获取缩略图路径
	 * 
	 * @param path
	 * @return
	 */
	public static String getSmallPictureUrl(String path) {
		return (path.lastIndexOf(".") == -1 ? path : path.substring(0, path.lastIndexOf("."))) + "_small.jpg";
	}

	/**
	 * 获取百度地图api链接地址
	 * 
	 * @param longitude
	 *            经度
	 * @param latitude
	 *            纬度
	 * @param title
	 *            标签
	 * @param content
	 * @return
	 * @throws UnsupportedEncodingException
	 *             String
	 */
	public static String getNavigateUrl(String longitude, String latitude, String title, String content)
			throws UnsupportedEncodingException {
		return "http://api.map.baidu.com/marker?location=" + latitude + "," + longitude + "&title="
				+ URLEncoder.encode(title, "utf-8") + "&content=" + URLEncoder.encode(content, "utf-8") + "&src="
				+ URLEncoder.encode("中资源|移动+", "utf-8") + "&output=html";
	}

	/**
	 * 处理urljsessionid
	 * 
	 * @param url
	 * @return String
	 */
	public static String operateJsessionidOfUrl(String url) {
		if (url.indexOf(";jsessionid=") == -1) {
			if (url.indexOf("?") == -1) {
				url += ";jsessionid=" + getRequest().getSession().getId();
			} else {
				String[] refferUrls = url.split("\\?", 2);
				url = refferUrls[0] + ";jsessionid=" + getRequest().getSession().getId() + "?" + refferUrls[1];
			}
		} else {
			if (url.indexOf("?") == -1) {
				url = url.substring(0, url.indexOf(";jsessionid=")) + ";jsessionid="
						+ getRequest().getSession().getId();
			} else {
				url = url.substring(0, url.indexOf(";jsessionid=")) + ";jsessionid="
						+ getRequest().getSession().getId() + url.substring(url.indexOf("?"));
			}
		}
		return url;
	}
	
	/**
	 * 处理urljsessionid
	 */
	public static String removeJsessionidOfUrl(String url) {
		if (url.indexOf(";jsessionid=") != -1) {
			url = url.substring(0, url.indexOf(";jsessionid="));
		}
		return url;
	}

	/**
	 * 获取原访问url
	 */
	public static String getRequestUrl() {
		return getRequestUrl(null);
	}

	/**
	 * 获取原访问url
	 */
	public static String getRequestUrl(List<String> filterParamNames) {
		String params = "?";
		for (Object name1 : getRequest().getParameterMap().keySet()) {
			String name = (String)name1;
			if (filterParamNames != null && filterParamNames.contains(name)) {
				continue;
			}
			try {
				params += name + "=" + URLEncoder.encode(getRequest().getParameter(name), "utf-8") + "&";
			} catch (UnsupportedEncodingException e) {
				logger.error(e.getMessage(), e);
				e.printStackTrace();
			}
		}
		return getRequest().getRequestURL() + params.substring(0, params.length() - 1);
	}

	/**
	 * 获取校验key
	 * 
	 * @return
	 */
	public static Cookie getCookieByName(String name) {
		Cookie[] cookies = getRequest().getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals(name)) {
					return cookie;
				}
			}
		}
		return null;
	}

	public static String getCookieValue(String name) {
		Cookie cookie = getCookieByName(name);
		if (cookie != null) {
			return cookie.getValue();
		}
		return null;
	}

	public static void setCookie(String name, String value, int maxAge) {
		Cookie cookie = new Cookie(name, value);
		cookie.setMaxAge(maxAge);
		cookie.setPath("/");
		getResponse().addCookie(cookie);
	}

	public static void setCookie(String name, String value) {
		setCookie(name, value, 24 * 60 * 60);
	}

	/**
	 * 是否ajax请求
	 */
	public static boolean isAjaxRequest() {
		return getRequest().getHeader("x-requested-with") != null
				&& getRequest().getHeader("x-requested-with").trim().toLowerCase().equals("xmlhttprequest");
	}

	/**
	 * 是否微信访问
	 * 
	 * @return boolean
	 */
	public static boolean getIsFromWechat() {
		String userAgent = getRequest().getHeader("user-agent");
		return userAgent != null && userAgent.indexOf("MicroMessenger") != -1;
	}

	/**
	 * 获取上下文HttpServletRequest
	 */
	public static HttpServletRequest getRequest() {
		RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
		return ((ServletRequestAttributes) attributes).getRequest();
	}

	/**
	 * 获取上下文HttpServletResponse
	 */
	public static HttpServletResponse getResponse() {
		RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
		return ((ServletRequestAttributes) attributes).getResponse();
	}

	/**
	 * 获取本地方言
	 * 
	 * @return String
	 */
	public static String getLocale() {
		RequestContext requestContext = new RequestContext(getRequest());
		if (requestContext.getLocale() == null) {
			return Constant.LOCALE_ZH;
		}
		return requestContext.getLocale().toString();
	}
	
	/**
	 * 获取当前语言key对应国际化描述
	 * 
	 * @param key
	 * @return
	 * String
	 */
	public static String getLocaleMessage(String key) {
		RequestContext requestContext = new RequestContext(getRequest());
		return requestContext.getMessage(key);
	}
}
